package com.gugee.ins.data.analysis.service.impl;

import com.gugee.common.thread.ScheduleTemplate;
import com.gugee.ins.common.dal.service.blogger.InsBloggerMainDao;
import com.gugee.ins.common.dal.service.media.InsMediaDao;
import com.gugee.ins.common.dal.util.InsMediaScoreClient;
import com.gugee.ins.common.dto.InsMediaScoreDto;
import com.gugee.ins.common.model.InsMediaScore;
import com.gugee.ins.common.model.mysql.blogger.InsBloggerMain;
import com.gugee.ins.data.analysis.config.InsAnalysisConfig;
import com.gugee.ins.data.analysis.service.InsAnalysisMediaScoreService;
import com.gugee.ins.data.blogger.es.core.MediaToEsService;
import com.gugee.ins.data.common.msg.InsBloggerMessage;
import com.xiguaji.boot.toolkit.ThreadPoolUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import java.util.*;
import java.util.concurrent.ForkJoinPool;

/**
 * InsAnalysisMediaScoreServiceImpl 服务
 * @author Huangxin
 */
@Slf4j
@Service
public class InsAnalysisMediaScoreServiceImpl implements InsAnalysisMediaScoreService {

    /**
     * 配置
     */
    @Autowired
    InsAnalysisConfig insAnalysisConfig;

    /**
     * insMediaScoreClient
     */
    @Autowired
    InsMediaScoreClient insMediaScoreClient;

    /**
     * 线程调度
     */
    @Autowired
    ScheduleTemplate scheduleTemplate;

    /**
     * InsBloggerDao
     */
    @Autowired
    InsBloggerMainDao insBloggerMainDao;

    /**
     * InsMediaDao
     */
    @Autowired
    InsMediaDao insMediaDao;

    /**
     *
     */
    @Autowired
    MediaToEsService mediaToEsService;

    /**
     * 线程池
     */
    ForkJoinPool forkJoinPool;

    /**
     * 线程名
     */
    private String workName = "insAnalysisMediaScore-worker";

    /**
     * 初始化线程池
     */
    @PostConstruct
    public void init() {
        forkJoinPool = ThreadPoolUtils.forkJoinPool(insAnalysisConfig.getInsAnalysisMediaScoreCorePollSize(), workName);
        scheduleTemplate.attach(workName, forkJoinPool);
    }

    /**
     * 处理 分析帖子分数 任务
     * @param insBloggerMessages
     */
    @Override
    public void handleAnalysisMediaScore(List<InsBloggerMessage> insBloggerMessages) {
        try {
            forkJoinPool.submit(() -> insBloggerMessages.parallelStream().forEach(msg -> {
                try {
                    // 分析语言
                    analysisMediaScore(msg);
                } catch (Exception ex) {
                    ex.printStackTrace();
                    log.error("insAnalysisMediaScore error. uid:{}, error :{}" ,
                            msg.getUid(),ex.getMessage());
                }
            })).get();
        } catch (Exception ex) {
            log.error("insAnalysisMediaScore thread error.  {}" ,  ex.getMessage());
        }
    }

    /**
     * 分析帖子分数
     *
     * @param insBloggerMessage
     */
    public void analysisMediaScore(InsBloggerMessage insBloggerMessage){
        long start = System.currentTimeMillis();
        long uid = insBloggerMessage.getUid();

        //限制时间范围
        long limitTime = start / 1000 - insAnalysisConfig.getInsAnalysisMediaScoreLatestDays() * 24 * 3600;

        // 获取计算过帖子平均值的播主信息
        InsBloggerMain insBloggerMain = getAnalysisAvgBloggerMain(uid,limitTime);
        if(insBloggerMain == null){
            return;
        }

        // 获取播主近期帖子的列表
        List<InsMediaScoreDto> insMediaScoreDtoList = insMediaDao.findAnalysisScoreMediaByUid(uid,limitTime);

        if(insMediaScoreDtoList != null && !insMediaScoreDtoList.isEmpty()){
            // 生成帖子分数分析对象
            InsMediaScore insMediaScore = insMediaScoreClient.getInsMediaScore(insBloggerMain,insMediaScoreDtoList);

            // 计算各个帖子分数
            insMediaScoreDtoList.forEach(insMediaScoreDto -> {
                double score = 0.0;
                try{
                    score = insMediaScore.getMediaScore(insMediaScoreDto);
                }catch (Exception e){
                    log.error("Ins Analysis Media Score error, shortcode:{},msg:{}", insMediaScoreDto.getShortcode(),e.getMessage());
                }
                insMediaScoreDto.setScore(score);
            });

            // 批量更新帖子分数
            insMediaDao.batchUpdateScore(insMediaScoreDtoList);
        }

        // 发送同步es
        try{
            mediaToEsService.handler(uid);
        }catch (Exception e){
            log.error("InsAnalysisMediaScore send to es error, uid:{},msg:{}", uid,e.getMessage());
        }

        if ((System.currentTimeMillis() - start) / 1000 > insAnalysisConfig.getInsAnalysisMediaScoreDebugTimeLimit()) {
            log.info("Ins Analysis Media Score uid:{} use time:{}s", insBloggerMessage.getUid(),(System.currentTimeMillis() - start) / 1000);
        }
    }

    /**
     * 获取计算过帖子平均值的播主信息
     * @param uid
     * @param limitTime
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public InsBloggerMain getAnalysisAvgBloggerMain(long uid, long limitTime){
        // 更新播主平均点赞数和平均评论数
        insBloggerMainDao.updateMediaAvg(uid,limitTime);

        // 获取播主近期帖子的平均点赞数和平均评论数
        return insBloggerMainDao.findByUid(uid);
    }
}
